package gui.cen.south;

import core.utils.Utils;
import gui.Segl2;
import gui.cen.Center;
import gui.processor.Processor;
import gui.processor.Worker;
import gui.utils.Borders;
import gui.utils.Para;
import gui.utils.Slider;
import gui.utils.SliderWrap;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;

/*Author: John Archer, Contact: john.archer.jpa@gmail.com*/
public class South extends JPanel implements MouseListener, Runnable{
    private int plotXPos;
    private CardLayout layout;
    private JPanel cp;
    private HeatMap hm;
    private Center center;
    private JButton left, right;
    private Segl2 SegL2;

    public South(Center center, Segl2 SegL2){
        super(new BorderLayout());
        this.center = center;
        this.SegL2 = SegL2;
        this.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));

        JPanel p = new JPanel(new BorderLayout());
        p.setBorder(BorderFactory.createEmptyBorder(0,-4,-3,-4));
        p.add(Utils.getButton(left = new JButton("<<<<<<<<<<"), 140, 25, Color.RED, new Color(178, 178, 178), (MouseListener)this, "Scroll Left"), BorderLayout.WEST);

        JPanel p0 = new JPanel();
        p0.setLayout(new BorderLayout());
        p0.add(new SliderWrap(Slider.SEQSIZE, 24, 8, Borders.SEQFONTSIZE, "+/-", 70, center), BorderLayout.WEST);

        //p0.add(new SliderWrap(Slider.INDEL_LEN_VIEW, EPara.MAX_INDEL-1, 1, Para.INDEL_LEN_VIEW, "Indel len.", 100, center), BorderLayout.CENTER);
        p0.add(new SliderWrap(Slider.SPEED, 1000, 1, Para.SPEED, "<<|>>", 70), BorderLayout.EAST);
        p.add(p0, BorderLayout.CENTER);
        p.add(Utils.getButton(right = new JButton(">>>>>>>>>>"), 140, 25, Color.RED, new Color(178, 178, 178), (MouseListener)this, "Scroll Right"), BorderLayout.EAST);
        add(p, BorderLayout.SOUTH);

        cp = new JPanel();
        cp.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
        layout = new CardLayout();
        cp.setLayout(layout);
        plotXPos = 5;
        updates();
        this.add(cp, BorderLayout.CENTER);
        this.setVisible(true);
    }

    @Override
    public void mouseClicked(MouseEvent me) {
        Object source = me.getSource();
        if(source == right){increment = Para.SPEED;}
        else if(source == left){increment = (-1) * Para.SPEED;}
        if((plotXPos + increment) < ((Para.PB.getRef().getDNA().length() * Borders.SEQ_CHAR_WIDTH) - this.getWidth()) && (plotXPos + increment) > 0){
            plotXPos = plotXPos + increment;
            updates();
        }
    }

    public void start(){
        Thread th = new Thread(this);
        th.start();
    }

    boolean pressed = false;
    int increment = 0;

    public void mousePressed(MouseEvent me){
        pressed = true;
        Object source = me.getSource();
        if(source == right){increment = Para.SPEED;}
        else if(source == left){increment = (-1 ) * Para.SPEED;}
        this.start();
    }

    @Override
    public void mouseReleased(MouseEvent me){pressed = false;}

    @Override
    public void mouseEntered(MouseEvent me) {}

    @Override
    public void mouseExited(MouseEvent me) {pressed = false;}

    @Override
    public void run() {
        if(increment>0){
            while(pressed && (plotXPos + increment) < ((Para.PB.getRef().getDNA().length() * Borders.SEQ_CHAR_WIDTH) - SegL2.getWidth())){
                plotXPos = plotXPos + increment;
                try{updates();Thread.sleep(100);}catch(Exception e){}
            }
        }
        else{
            while(pressed && (plotXPos + increment)  > 0){
                plotXPos = plotXPos + increment;
                try{updates();Thread.sleep(100);}catch(Exception e){}
            }
        }
    }

    public void updatePlots(){
        if(hm==null){
            cp.add(hm = new HeatMap(), "heat");
            layout.show(cp, "heat");
        }
        else{hm.updatePlots();}
    }

    private static boolean busy = false;
    private void updates(){
        if(busy==false){
            busy = true;
            try{toReplaceTitlesPanelJob();}catch(Exception e){}
            try{center.updateTable();}catch(Exception e){}
            try{center.updateReads();}catch(Exception e){}
            try{createTreeDar();}catch(Exception e){}
            try{updatePlots();}catch(Exception e){}
            busy = false;
        }
    }

    public void createTreeDar(){
        Processor guip = new Processor(this);
        guip.setTask(Para.TASK_TREEDAR);
        Worker sl = new Worker(guip);
        sl.execute();
    }

    public void toReplaceTitlesPanelJob(){
        try{
            Para.TPOS = (int)Math.round(Math.ceil(plotXPos/Borders.SEQ_CHAR_WIDTH));
            int endOnRef = Para.TPOS + (int)Math.round(Math.ceil(SegL2.getWidth()/Borders.SEQ_CHAR_WIDTH));
            int startReadi = -1;int count = 0;
            for(int z=0; z<Para.PB.getSize(); z++){
                if(Para.PB.getRead(z).getEnd() > Para.TPOS && Para.PB.getRead(z).getStart() <= endOnRef){
                    startReadi = z;
                    for(int j=z; j<Para.PB.getSize(); j++){
                        if(Para.PB.getRead(j).getStart() < endOnRef){count++;}
                        else{j = Para.PB.getSize();}
                    }
                    z = Para.PB.getSize();
                }
            }
            if(startReadi==-1){Para.RTD.clear();}
            else{
                int endReadi = startReadi + count;
                if(endReadi > Para.PB.getSize()){endReadi = Para.PB.getSize();}
                Para.RTD.clear();
                for(int t=startReadi; t<endReadi; t++){Para.RTD.add(Para.PB.getRead(t));}
            }
        }
        catch(Exception e){}
    }
}